package com.qf.file.util;

import com.madgag.gif.fmsware.AnimatedGifEncoder;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author 汤奇
 * @version V1.0
 * @Project BookPro
 * @Package com.qf.file.util
 * @Description: 视频截帧产生GIF的方法
 * @Date 2022/8/5 19:50
 */
public class GifUtil {
    /**
     * 定义默认的步长
     */
    private static final Integer DEFAULT_MARGIN=2;

    /**
     * 定义默认的帧频率
     */
    private static final Integer DEFAULT_FRAME_RATE=10;

    /**
     * 指定一个视频，生成gif与jpg
     * @param filePath 原视频文件的位置
     * @param startFrame 起始帧的位置
     * @param frameCount 截帧的总帧数
     * @param frameRate 帧频率
     * @param margin 步长
     */
    public static void buildGifAndJpg(String filePath,int startFrame,int frameCount,
                                      Integer frameRate,Integer margin){
        try{
            if(frameRate==null){
                frameRate=DEFAULT_FRAME_RATE;
            }
            if(margin==null){
                margin=DEFAULT_MARGIN;
            }
            //文件路径、文件名都不变，后缀改为gif
            String gifPath=filePath.substring(0,filePath.lastIndexOf("."))
                    +".gif";
            //文件输出流
            FileOutputStream targetFile=new FileOutputStream(gifPath);
            //使用ffmpeg引擎逐帧读取。
            FFmpegFrameGrabber ff=new FFmpegFrameGrabber(filePath);
            //创建一个java的2d画面转换器
            Java2DFrameConverter converter=new Java2DFrameConverter();
            //让ffmpeg开始工作
            ff.start();

            //读取视频总帧数
            Integer videoLength=ff.getLengthInFrames();
            if(startFrame>videoLength||(startFrame+frameCount*margin)>videoLength){
                //帧数不够用
                startFrame=1;
                frameCount=(videoLength-startFrame-margin)/margin;
            }

            //设置ffmpeg加载的位置
            ff.setFrameNumber(startFrame);

            //实例化一个gif编码器
            AnimatedGifEncoder en=new AnimatedGifEncoder();
            //给gif设置帧频率
            en.setFrameRate(frameRate);
            //设置gif无限循环
            en.setRepeat(0);
            //让gif编码器对目标文件进行编码
            en.start(targetFile);

            //设置生成视频封面的标志位
            boolean poster=false;


            //逐帧：
            for (int i = 0; i < frameCount; i++) {
                Frame frame = ff.grabFrame();
                if(frame!=null){
                    BufferedImage bufferedImage=converter.convert(frame);
                    if(!poster){
                        String jpgPath=filePath.substring(0,filePath.lastIndexOf("."))
                                +".jpg";
                        ImageIO.write(bufferedImage,"jpg",new File(jpgPath));
                        poster=true;
                    }

                    //把一帧画面放到gif编码器中
                    en.addFrame(bufferedImage);
                    //每一次都设置gif的下一次采集视频帧的位置
                    ff.setFrameNumber(ff.getFrameNumber()+margin);
                }
            }
            en.finish();
            ff.stop();
            ff.close();

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        buildGifAndJpg("D:\\冉海峰.m4v",200,20,4,10);
    }
}
